package com.atguigu.tingshu.common.configure;

import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.common.pojo.TingShuCorrelationData;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

@Configuration
@Slf4j
public class TingShuRabbitmqConfig {
    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Bean
    public void init() {
        //判断消息是否到达交换机，不管到没到都会回调
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {
            if (ack) {
                log.info("消息到达交换机:{},correlationData:{}", cause, correlationData);
                return;
            }
            //消息未到达交换机
            log.error("消息未到达交换机：{} , correlationData:{} ", cause, correlationData);
            if (correlationData == null) return;
            //可以尝试从correlationData中获取消息内容 +  交换机 + 路由key 尝试重新发送消息
            TingShuCorrelationData tingShuCorrelationData = (TingShuCorrelationData) correlationData;
            //需要重新发送：尝试重发
            if (tingShuCorrelationData.getIsRetry() && tingShuCorrelationData.getRetryCount() <
                    tingShuCorrelationData.getLimit()) {
                String exchange = tingShuCorrelationData.getExchange();
                String routingKey = tingShuCorrelationData.getRoutingKey();
                Object message = tingShuCorrelationData.getMsg();
                tingShuCorrelationData.setRetryCount(tingShuCorrelationData.getRetryCount() + 1);
                rabbitTemplate.convertAndSend(exchange, routingKey, message, tingShuCorrelationData);
            } else {
                //不重发，记录失败日志: 发送告警邮件 给模块负责人
                log.error("消息：{} 发送失败，未到达交换机", JSON.toJSONString(correlationData));
            }

        });

        //判断消息是否到达队列，只有未到达队列时  回调
        rabbitTemplate.setReturnsCallback(returned -> {
            Object idObj = returned.getMessage().getMessageProperties()
                    .getHeader("spring_returned_message_correlation");
            if (idObj == null) {
                log.error("消息未到达队列：{} ", JSON.toJSONString(returned));
                return;
            }
            Object correlationData = redisTemplate.opsForValue().get("mq:" + idObj);
            if (correlationData == null) {
                log.error("消息未到达队列：{} ", JSON.toJSONString(returned));
                return;
            }
            TingShuCorrelationData tingShuCorrelationData = (TingShuCorrelationData) correlationData;

            if (!tingShuCorrelationData.getIsRetry() || tingShuCorrelationData.getRetryCount() >= tingShuCorrelationData.getLimit()) {
                log.error("消息未到达队列，消息内容：{} ", JSON.toJSONString(tingShuCorrelationData));
                return;
            }

            String exchange = tingShuCorrelationData.getExchange();
            String routingKey = tingShuCorrelationData.getRoutingKey();
            Object message = tingShuCorrelationData.getMsg();
            tingShuCorrelationData.setRetryCount(tingShuCorrelationData.getRetryCount() + 1);
            //更新redis中的TINGSHUCorrelationData的重试次数
            redisTemplate.opsForValue().set("mq:" + tingShuCorrelationData.getId(), tingShuCorrelationData);
            rabbitTemplate.convertAndSend(exchange, routingKey, message, tingShuCorrelationData);
        });
    }
}